
var markdown = new showdown.Converter();

var vue = new Vue({
    el: "#app",
    
    data: {
        env: ENV,
        ENV_FILE,
        ENV_SERVER,
        ENV_ELECTRON,
        ENV_TAURI,

        companyListVisible: false,

        // ==================================================================
        currentCompanyId: 1,
        companys: [],

        currentProjectId: 1,
        projects: [],
        searchedProject: "",

        currentItemId: 1,
        items: [],
        searchedItemName: "",

        // ==================================================================
        // filters
        filterKeyword: "",
        // filterList: [],
        activeIndex: -1,

        // ==================================================================
        // company
        companyVisible: false,
        modifyComapny: {
            id: 1,
            name: "",
            orders: 10,
        },
        companyDoing: "edit",   // edit/add

        // project
        projectVisible: false,
        modifyProject: {
            id: 1,
            name: "",
            orders: 10,
            cId: 1,
        },
        projectDoing: "edit",

        // item
        itemVisible: false,
        itemDoing: "edit",
        modifyItem: {
            id: 1,
            name: "a",
            url: "",
            content: "c",
            orders: 10,
            pId: 1,
        },
        addType: 1,
        insertIndex: 0,

        // ==================================================================
        // event
        keyEventHandle: null,
        keyUpEvents: null,
        bodyClickEvent: null,

        // ==================================================================
        // toast
        toastVisible: false,
        toastContent: "",

        // ==================================================================
        password: "",
    },

    computed: {
        // ==================================================================
        // filters
        filterList() {
            if (!this.filterKeyword) return [];
            var pIds = this.currentProjects.map(project => project.id);
            var lowercaseKeyword = this.filterKeyword.toLowerCase();
            return this.items
                .filter(item => pIds.indexOf(item.pId) >= 0)
                .filter(item => item.name.toLowerCase().indexOf(lowercaseKeyword) >= 0)
        },

        //
        username() {
            return getUsername() || "username"
        },

        // ==================================================================
        // with projects
        companyList() {
            var companyList = JSON.parse(JSON.stringify(this.companys));

            companyList.forEach(company => {
                company.projectList = this.projects.filter(project => project.cId == company.id);
            })

            return companyList;
        },
        currentCompany() {
            return this.companys.find(company => company.id == this.currentCompanyId);
        },

        currentProjects() {
            return this.projects.filter(project => project.cId == this.currentCompanyId);
        },
        currentProject() {
            return this.projects.find(project => project.id == this.currentProjectId);
        },
       
        currentItems() {
            this.decodeItems();
            return this.items.filter(item => item.pId == this.currentProjectId);
        },
        currentItem() {
            return this.items.find(item => item.id == this.currentItemId);
        },
    },

    methods: {
        // ==================================================================
        // common
        openLink(url) {
            apis.openLink(url);
        },

        // ==================================================================
        // markdown
        toHTML(str) {
            if (!str) return "";
            setTimeout(() => {
                mermaid.init();
            }, 0)
            var content = this.transformFlowToMermaid(str);
            content = this.addEyeAndCopyForPassword(content);
            content = markdown.makeHtml(content);
            return this.addHrefTarget(content);
        },
        addHrefTarget(str) {
            return str
                .replace(/ href=/g, " class='outer-link' target='_blank' data-href=");
        },
        transformFlowToMermaid(str) {
            str = str.replaceAll(/```mermaid([^`]+)```/g, (group0, group1) => {
                return '<div class="mermaid">'+ group1 +'</div>';
            })
            return str;
        },
        addEyeAndCopyForPassword(str) {
            return str.replaceAll(/(?<=\s)`(\S+)`(?=\s|$)/g, (group0, group1) => {
                return "<code class='app-passwd'>"+ group1 + "</code>" 
                    + "<i class='passwd-eye'></i> <i class='passwd-copy' ></i>";
            });
        },
        // decrypt
        decodeItems() {
            this.items.filter(item => item.pId == this.currentProjectId)
                .forEach(item => {
                    if (!item.decrypted) {
                        encryptor.decrypt(item.content, this.password).then(originContent => {
                            item.content = originContent;
                            item.decrypted = true;
                        }).catch(e => {
                            console.log(e)
                        })
                    }
                })
        },

        // ==================================================================
        // toast
        toast(content) {
            this.toastContent = content;
            this.toastVisible = true;

            setTimeout(() => {
                this.toastVisible = false;
            }, 1500);
        },
        appClick() {
            this.companyListVisible = false;
        },

        // ==================================================================
        // company
        changeCompany(compayId) {
            if(compayId) {
                this.currentCompanyId = compayId;
            } else {
                if (this.companys && this.companys.length > 0) {
                    this.currentCompanyId = this.companys[0].id;
                } else {
                    this.currentCompanyId = 0;
                }
            }

            if (this.currentCompanyId > 0) {
                var newProjectId = this.currentProjects.length > 0 ? this.currentProjects[0].id : 0;
                this.changeProject(newProjectId);
            } else {
                this.getProjects()
            }
            this.companyListVisible = false;
        },
        showCompany() {
            this.companyVisible = true;
        },
        hideCompany() {
            this.companyVisible = false;
        },
        getCompanys() {
            return apis.getAllCompany().then(res => {
                this.companys = res;
            })
        },
        validCompany(company) {
            return company.name && company.name.trim()
        },
        addCompany() {
            if (!this.validCompany(this.modifyComapny)) return;

            this.modifyComapny.orders = parseInt(this.modifyComapny.orders)
            return apis.addCompany(this.modifyComapny).then(lastId => {
                this.toast("Add Company Success");
                this.getCompanys().then(() => {
                    this.changeCompany(lastId)
                })
                this.hideCompany();
            })
        },
        saveCompany() {
            if (!this.validCompany(this.modifyComapny)) return;
            
            this.modifyComapny.orders = parseInt(this.modifyComapny.orders)
            return apis.updateCompany(this.modifyComapny).then(data => {
                this.toast("Update Company Success");
                this.getCompanys();
                this.hideCompany();
            })
        },
        deleteCompany() {
            if (confirm("Are you sure to delete the company and all projects in it?")) {
                apis.deleteCompany(this.modifyComapny.id).then(() => {
                    this.toast("Delete Company Success");
                    this.getCompanys().then(() => {
                        this.changeCompany();
                    });
                    this.hideCompany();
                })
            }
        },

        submitAddCompany() {
            this.companyDoing = "add";
            this.modifyComapny.name = "";
            this.modifyComapny.id = 0;
            this.modifyComapny.orders = 10;
            this.showCompany();
        },
        submitEditCompany(company) {
            this.companyDoing = "edit";
            this.modifyComapny = this.deepcopy(company);
            this.showCompany();
        },

        // ==================================================================
        // project
        getProjectsByCompanyId(cId) {
            return projects.filter(project => project.cId == cId);
        },
        changeProject(id) {
            if (id) {
                this.currentProjectId = id;
            } else {
                if (this.currentProjects && this.currentProjects.length > 0) {
                    this.currentProjectId = this.currentProjects[0].id;
                } else {
                    this.currentProjectId = 0;
                }
            }

            if (this.currentProjectId > 0) {
                this.currentItemId = this.currentItems.length > 0 ? this.currentItems[0].id : 0;
            } else {
                this.getItems()
            }
        },
        showProject() {
            this.modifyProject.cId = this.currentCompany.id;
            this.projectVisible = true;
        },
        hideProject() {
            this.projectVisible = false;
        },
        getProjects() {
            return apis.getAllProject().then(res => {
                this.projects = res || [];
            })
        },
        validProject(project) {
            return project.name && project.name.trim()
        },
        addProject() {
            if (!this.validProject(this.modifyProject)) return;

            this.modifyProject.orders = parseInt(this.modifyProject.orders)
            return apis.addProject(this.modifyProject).then(lastId => {
                this.toast("Add Project Success");
                this.getProjects().then(() => {
                    this.changeProject(lastId)
                });
                this.hideProject();
            })
        },
        updateProject() {
            if (!this.validProject(this.modifyProject)) return;

            this.modifyProject.orders = parseInt(this.modifyProject.orders)
            return apis.updateProject(this.modifyProject).then((data) => {
                this.toast("Update Project Success");
                this.getProjects();
                this.hideProject();
            })
        },
        deleteProject() {
            if (confirm("Are you sure?")) {
                apis.deleteProject(this.modifyProject.id).then(() => {
                    this.toast("Delete Project Success");
                    this.getProjects().then(() => {
                        this.changeProject()
                    })
                    this.hideProject();
                })
            }
        },
      
        submitAddProject(companyId) {
            this.projectDoing = 'add';
            this.modifyProject.id = 0;
            this.modifyProject.name = "";
            this.modifyProject.cId = companyId || this.currentCompanyId;
            this.modifyProject.orders = 10;
            this.showProject();
        },
        submitUpdateProject(project) {
            this.projectDoing = 'edit';
            this.modifyProject = this.deepcopy(project || this.currentProject);
            this.showProject();
        },

        // ==================================================================
        // item
        showItem() {
            // 自动扩展 textarea 高度
            this.itemVisible = true;
            var textarea = document.querySelector(".js-textarea");
            textarea.style.height = "auto";
            this.$nextTick(() => {
                textarea.style.height = textarea.scrollHeight + 2 + "px";
            })
        },
        hideItem() {
            this.itemVisible = false;
        },
        getItems() {
            return apis.getAllItem().then(res => {
                this.items = res || [];
            })
        },
        validItem(item) {
            return item.name && item.content && item.name.trim() && item.content.trim()
        },
        addItem() {
            if (!this.validItem(this.modifyItem)) return;

            this.modifyItem.orders = parseInt(this.modifyItem.orders)
            encryptor.encrypt(this.modifyItem.content, this.password).then(secretCon => {
                apis.addItem({
                    ...this.modifyItem,
                    content: secretCon
                }).then(() => {
                    this.toast("Add Item Success");
                    this.getItems();
                    this.hideItem();
                })
            })
        },
        updateItem() {
            if (!this.validItem(this.modifyItem)) return;

            this.modifyItem.orders = parseInt(this.modifyItem.orders)
            encryptor.encrypt(this.modifyItem.content, this.password).then(secretCon => {
                apis.updateItem({
                    ...this.modifyItem,
                    content: secretCon
                }).then(data => {
                    this.toast("Update Item Success");
                    this.getItems();
                    this.hideItem();
                })
            })
        },
        deleteItem() {
            if (confirm("Are you sure to delete the item?")) {
                apis.deleteItem(this.modifyItem.id).then(() => {
                    this.toast("Delete Item Success");
                    this.getItems();
                    this.hideItem();
                })
            }
        },
        submitAddItem(projectId) {
            this.itemDoing = 'add';
            this.modifyItem.id = 0;
            this.modifyItem.name = "";
            this.modifyItem.url = "";
            this.modifyItem.content = "";
            this.modifyItem.pId = projectId || this.currentProjectId;
            this.modifyItem.orders = 10;
            this.showItem();
        },
        submitUpdateItem(item) {
            this.modifyItem = this.deepcopy(item);
            this.itemDoing = 'edit';
            this.showItem();
        },
        toItem(item) {
            this.currentItemId = item.id;
            this.currentProjectId = item.pId;
            var project = this.projects.find(p => p.id === item.pId);
            this.currentCompanyId = project.cId;

            this.filterKeyword = "";
        },


        // ==================================================================
        init() {
            Promise.all([this.getCompanys(), this.getProjects(), this.getItems()]).then(() => {
                this.changeCompany();
            });
        },

        // ================================================================== 
        // save
        saveToLocalhost() {
            apis.saveDb().then(() => {
                this.toast("Save Success");
            })
        },

        // ==================================================================-------
        // common
        deepcopy(obj) {
            if (typeof obj != 'object' && !Array.isArray(obj)) {
                return {};
            }

            return JSON.parse(JSON.stringify(obj));
        },

        bindEvents() {
            document.body.addEventListener("click", this.bodyClickEvent);
        },

        unbindEvents() {
            document.body.removeEventListener("click", this.bodyClickEvent);
        }
    },

    created() {
        getUserSecretKey().then((originSecretKey) => {
            this.password = originSecretKey
            this.init();
            this.bindEvents();
        }).catch(e => {
            console.log(e)
            window.location.replace("./login.html")
        })
    }
})